import logging
import psycopg2
import requests
import json
from settings import *
from .wx_user_table_methods import WxUserTableMethods


logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

'''
https://api.weixin.qq.com/sns/jscode2session
请求参数
属性 	类型 	必填 	说明
appid 	string 	是 	小程序 appId
secret 	string 	是 	小程序 appSecret
js_code 	string 	是 	登录时获取的 code，可通过wx.login获取
grant_type 	string 	是 	授权类型，此处只需填写 authorization_code
返回参数
属性 	类型 	说明
session_key 	string 	会话密钥
unionid 	string 	用户在开放平台的唯一标识符，若当前小程序已绑定到微信开放平台账号下会返回，详见 UnionID 机制说明。
errmsg 	string 	错误信息
openid 	string 	用户唯一标识
errcode 	int32 	错误码
'''

class WxLoginMethods: 

    def __init__(self, conn, cur):
        self.cursor = cur
        self.conn = conn

    def wx_jscode2session(self,js_code, grant_type='authorization_code'):
        '''
        微信小程序登录
        :param js_code: 小程序登录时获取的 code
        :param grant_type: 授权类型，此处只需填写 authorization_code
        :return: 
        {
            "openid":"xxxxxx",
            "session_key":"xxxxx",
            "unionid":"xxxxx",
            "errcode":0,
            "errmsg":"xxxxx"
        }
 
        错误码
        错误码 	错误码取值 	解决方案
        40029 	code 无效 	js_code无效
        45011 	api minute-quota reach limit  mustslower  retry next minute 	API 调用太频繁，请稍候再试
        40226 	code blocked 	高风险等级用户，小程序登录拦截 。风险等级详见用户安全解方案
        -1 	system error 	系统繁忙，此时请开发者稍候再试

        '''

        url = "https://api.weixin.qq.com/sns/jscode2session"

        params = {
            "appid": WECHAT_APP_ID,
            "secret": WECHAT_APP_SECRET,
            "js_code": js_code,
            "grant_type": grant_type
        }

        r = requests.get(url, params=params)

        if r.status_code == 200:
            wx_jscode2session_data =  {
                "openid": None,
                "session_key": None,
                "unionid": None,
                "errcode":0,
                "errmsg": "success"
            }

            wx_jscode2session_data.update(r.json())

            logger.info(f"wx_jscode2session success: {r.json()}")
            # {'session_key': '/Mc4SKuzRgzPDsxyOJd8/g==', 'openid': 'oK4IS7XSI546UWoBk8I5CF3izfDY'}

            if wx_jscode2session_data.get('errcode') == 0:
                # 成功获取到session_key和openid，插入数据库
                self.insert_wx_jscode2session(wx_jscode2session_data)

                wx_user_data = WxUserTableMethods(self.conn, self.cursor)
                if not wx_user_data.get_user_by_open_id(wx_jscode2session_data['openid']):
                    # 未注册用户，插入用户信息
                    wx_user_data.insert_user(wx_jscode2session_data['openid'])

            return wx_jscode2session_data

        else:
            logger.error(f"wx_longin_user error: {r.status_code}")
            return None
        
    def insert_wx_jscode2session(self, wx_jscode2session_data):
        '''
        :param wx_jscode2session_data: {
            "openid":"xxxxxx",
            "session_key":"xxxxx",
            "unionid":"xxxxx",
            "errcode":0,
            "errmsg":"xxxxx"
        }
        
        -- 微信小程序用户登录日志表
        CREATE TABLE IF NOT EXISTS wx_user_login_log (
            log_id SERIAL PRIMARY KEY, -- 日志ID，唯一标识每个登录日志
            session_key VARCHAR(50)  NOT NULL, -- 用户在微信小程序登录时生成的session_key
            unionid VARCHAR(50), -- 用户在开放平台的唯一标识 没有绑定开放平台的小程序时为null
            errmsg VARCHAR(50) NOT NULL, -- 错误信息
            openid VARCHAR(50) NOT NULL, -- 用户在微信小程序中的唯一标识
            errcode INT NOT NULL, -- 错误码
            login_time TIMESTAMP DEFAULT now() -- 登录时间
        );'''

        sql = "INSERT INTO wx_user_login_log (session_key, unionid, errmsg, openid, errcode) VALUES (%s, %s, %s, %s, %s)"
        values = (
            wx_jscode2session_data['session_key'],
            wx_jscode2session_data['unionid'],
            wx_jscode2session_data['errmsg'],
            wx_jscode2session_data['openid'],
            wx_jscode2session_data['errcode']
        )
        try:
            self.cursor.execute(sql, values)
            self.conn.commit()
            logger.info(f"insert_wx_jscode2session success: {values}")
            return True
        except Exception as e:
            logger.error(f"insert_wx_jscode2session error: {e}")
            return False

        




